home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / scheme / schmlbrr / schem_lb.lha / unsupported / CScheme / extend-syntax-7.0.scm < prev    next >
Encoding:
Text File  |  1993-07-16  |  12.0 KB  |  413 lines

  1. ;;; extend-syntax.scm
  2. ;;; August 7, 1989
  3. ;;; Ported from chez to mitscheme M. Radle, M. Montenyohl and E. Elberson
  4. ;;; new macros include:  when, unless,  and
  5. ;;; kerror ('k' to differentiate from mitscheme's 'error' function.)
  6. ;;; The following functions were added:
  7. ;;;  gensym, duplicate-symbols, box, unbox, set-box!.
  8. ;;; April 15, 1991 (markf@zurich.ai.mit.edu)
  9. ;;; Added define-macro-both to define macros in this file and in
  10. ;;; user-initial-syntax-table.
  11.  
  12. (syntax-table-define user-initial-syntax-table 'define-macro-both
  13.   (macro (pattern . body)
  14.     `(begin
  15.        (define-macro ,pattern ,@body)
  16.        (syntax-table-define user-initial-syntax-table ',(car pattern)
  17.      (macro ,(cdr pattern)
  18.        ,@body)))))
  19.  
  20. (define-macro (define-macro-both pattern . body)
  21.   `(begin
  22.      (define-macro ,pattern ,@body)
  23.      (syntax-table-define user-initial-syntax-table ',(car pattern)
  24.        (macro ,(cdr pattern)
  25.      ,@body))))
  26.  
  27. (define gensym generate-uninterned-symbol)
  28.  
  29. (define gensym generate-uninterned-symbol)
  30.  
  31. (define-macro-both (unless *cond . e1 ) `(if (not ,*cond) (begin ,@e1) #f))
  32.  
  33. (define-macro-both (when *cond . e1) `(if ,*cond (begin ,@e1) #f))
  34.  
  35. (define-macro (kerror msg-line . args)
  36.   `(begin
  37.      (format ,msg-line ,@args)
  38.      (error " ")))
  39.  
  40.  
  41.  
  42. ;;; extend.ss
  43. ;;; Copyright (C) 1987 R. Kent Dybvig
  44. ;;; Permission to copy this software, in whole or in part, to use this
  45. ;;; software for any lawful purpose, and to redistribute this software
  46. ;;; is granted subject to the restriction that all copies made of this
  47. ;;; software must include this copyright notice in full.
  48.  
  49. ;;; The basic design of extend-syntax is due to Eugene Kohlbecker.  See
  50. ;;; "E. Kohlbecker: Syntactic Extensions in the Programming Language Lisp",
  51. ;;; Ph.D.  Dissertation, Indiana University, 1986."  The structure of "with"
  52. ;;; pattern/value clauses, the method for compiling extend-syntax into
  53. ;;; Scheme code, and the actual implementation are due to Kent Dybvig.
  54.  
  55.  
  56. ;;; August 7, 1989
  57. ;;; We modified Kent's original code as follows:
  58. ;;;     . use define-macro to define extend-syntax
  59. ;;;    . All 'defines' are nested inside the definition of extend-syntax.
  60. ;;;    . Syntax-Match? had to be defined local to extend-syntax's definition
  61. ;;;       and local to the call to define-macro that appears in the 
  62. ;;;      expansion for extend-syntax. (see bottom of file).
  63. ;;; April 15, 1991 (markf@zurich.ai.mit.edu)
  64. ;;; Use syntax-table-define instead of define-macro.
  65. ;;; Put syntax-match in the proper place.
  66.  
  67. (syntax-table-define user-initial-syntax-table 'extend-syntax
  68.   (macro (keys . clauses)
  69.  
  70.     (define gensym generate-uninterned-symbol)
  71.     (define box (lambda (x) (cons x #f)))
  72.     (define unbox (lambda (x) (car x)))
  73.     (define set-box! (lambda (x v) (set-car! x v)))
  74.     
  75.     (define duplicate-symbols
  76.       (lambda ( list )
  77.     (unless (null? list)
  78.         (when (memq (car list) (cdr list))
  79.               (cons (car list)
  80.                 ( duplicate-symbols (cdr list)))))))
  81.  
  82.  
  83.  
  84.     (define id
  85.       (lambda (name *access control)
  86.     (list name *access control)))
  87.     (define id-name car)
  88.     (define id-access cadr)
  89.     (define id-control caddr)
  90.  
  91.     (define loop
  92.       (lambda ()
  93.     (box '())))
  94.     (define loop-ids unbox)
  95.     (define loop-ids! set-box!)
  96.  
  97.     (define c...rs
  98.       `((car caar . cdar)
  99.         (cdr cadr . cddr)
  100.         (caar caaar . cdaar)
  101.         (cadr caadr . cdadr)
  102.         (cdar cadar . cddar)
  103.         (cddr caddr . cdddr)
  104.         (caaar caaaar . cdaaar)
  105.         (caadr caaadr . cdaadr)
  106.         (cadar caadar . cdadar)
  107.         (caddr caaddr . cdaddr)
  108.         (cdaar cadaar . cddaar)
  109.         (cdadr cadadr . cddadr)
  110.         (cddar caddar . cdddar)
  111.         (cdddr cadddr . cddddr)))
  112.  
  113.     (define add-car
  114.       (lambda (*access)
  115.     (let ((x (and (pair? *access) (assq (car *access) c...rs))))
  116.       (if (null? x)
  117.           `(car ,*access)
  118.           `(,(cadr x) ,@(cdr *access))))))
  119.  
  120.     (define add-cdr
  121.       (lambda (*access)
  122.     (let ((x (and (pair? *access) (assq (car *access) c...rs))))
  123.       (if (null? x)
  124.           `(cdr ,*access)
  125.           `(,(cddr x) ,@(cdr *access))))))
  126.  
  127.  
  128.     (define checkpat
  129.       (lambda (keys pat exp)
  130.     (let ((vars (let f ((x pat) (vars '()))
  131.               (cond
  132.                ((pair? x)
  133.             (if (and (pair? (cdr x))
  134.                  (eq? (cadr x) '...)
  135.                  (null? (cddr x)))
  136.                 (f (car x) vars)
  137.                 (f (car x) (f (cdr x) vars))))
  138.                ((symbol? x)
  139.             (cond
  140.              ((memq x keys) vars)
  141.              ((or (eq? x 'with) (eq? x '...))
  142.               (kerror
  143.                "EXTEND-SYNTAX: Invalid context for ~o in ~o"
  144.                x exp))
  145.              (else (cons x vars))))
  146.                (else vars)))))
  147.       (let ((dupls (duplicate-symbols vars)))
  148.         (unless (null? dupls)
  149.             (kerror "EXTEND-SYNTAX: duplicate pattern variable name ~o in ~o"
  150.                 (car dupls) exp))))))
  151.  
  152.     (define parse
  153.       (lambda (keys pat acc cntl ids)
  154.     (cond
  155.      ((symbol? pat)
  156.       (if (memq pat keys)
  157.           ids
  158.           (cons (id pat acc cntl) ids)))
  159.      ((pair? pat)
  160.       (cons (id pat acc cntl)
  161.         (if (equal? (cdr pat) '(...))
  162.             (let ((x (gensym)))
  163.               (parse keys (car pat) x (id x acc cntl) ids))
  164.             (parse keys (car pat) (add-car acc) cntl
  165.                (parse keys (cdr pat) (add-cdr acc) cntl ids)))))
  166.      (else ids))))
  167.  
  168.     (define pattern-variable?
  169.       (lambda (sym ids)
  170.     (memq sym (map id-name ids))))
  171.  
  172.     (define gen
  173.       (lambda (keys exp ids loops qqlev)
  174.     (cond
  175.      ((lookup exp ids) =>
  176.                (lambda (id)
  177.                  (add-control! (id-control id) loops)
  178.                  (list 'unquote (id-access id))))
  179.      ((not (pair? exp)) exp)
  180.      (else
  181.       (cond
  182.        ((and (syntax-match? '(quasiquote *) exp)
  183.          (not (pattern-variable? 'quasiqote ids)))
  184.         (list 'unquote
  185.           (list 'list
  186.             ''quasiquote
  187.             (make-quasi
  188.              (gen keys (cadr exp) ids loops
  189.                   (if (= qqlev 0) 0 (+ qqlev 1)))))))
  190.        ((and (syntax-match? '(* *) exp)
  191.          (memq (car exp) '(unquote unquote-splicing))
  192.          (not (pattern-variable? (car exp) ids)))
  193.         (list 'unquote
  194.           (list 'list
  195.             (list 'quote (car exp))
  196.             (make-quasi
  197.              (if (= qqlev 1)
  198.                  (gen-quotes keys (cadr exp) ids loops)
  199.                  (gen keys (cadr exp) ids loops
  200.                   (- qqlev 1)))))))
  201.        ((and (eq? (car exp) 'with)
  202.          (not (pattern-variable? 'with ids)))
  203.         (unless (syntax-match? '(with ((* *) ...) *) exp)
  204.                     (kerror "EXTEND-SYNTAX: invalid 'with' form ~o" exp))
  205.         (checkpat keys (map car (cadr exp)) exp)
  206.         (list 'unquote
  207.           (gen-with
  208.            keys
  209.            (map car (cadr exp))
  210.            (map cadr (cadr exp))
  211.            (caddr exp)
  212.            ids
  213.            loops)))
  214.        ((and (pair? (cdr exp)) (eq? (cadr exp) '...))
  215.         (let ((x (loop)))
  216.           (gen-cons (list 'unquote-splicing
  217.                   (make-loop x (gen keys (car exp) ids
  218.                         (cons x loops) qqlev)))
  219.             (gen keys (cddr exp) ids loops qqlev))))
  220.        (else
  221.         (gen-cons (gen keys (car exp) ids loops qqlev)
  222.               (gen keys (cdr exp) ids loops qqlev))))))))
  223.  
  224.     (define gen-cons
  225.       (lambda (head tail)
  226.     (if (null? tail)
  227.         (if (syntax-match? '(unquote-splicing *) head)
  228.         (list 'unquote (cadr head))
  229.         (cons head tail))
  230.         (if (syntax-match? '(unquote *) tail)
  231.         (list head (list 'unquote-splicing (cadr tail)))
  232.         (cons head tail)))))
  233.  
  234.     (define gen-with
  235.       (lambda (keys pats exps body ids loops)
  236.     (let ((temps (map (lambda (x) (gensym)) pats)))
  237.       `(let (,@(map (lambda (t e) `(,t ,(gen-quotes keys e ids loops)))
  238.             temps
  239.             exps))
  240.          ,@(let f ((pats pats) (temps temps))
  241.          (if (null? pats)
  242.              '()
  243.              (let ((m (match-pattern '() (car pats)))
  244.                (rest (f (cdr pats) (cdr temps))))
  245.                (if (eq? m '*)
  246.                (f (cdr pats) (cdr temps))
  247.                `((unless (syntax-match? ',m ,(car temps))
  248.                                      (kerror "~o: ~o does not fit 'with' pattern ~o"
  249.                          ',(car keys)
  250.                          ,(car temps)
  251.                          ',(car pats)))
  252.                  ,@(f (cdr pats) (cdr temps)))))))
  253.          ,(let f ((pats pats) (temps temps) (ids ids))
  254.         (if (null? pats)
  255.             (make-quasi (gen keys body ids loops 0))
  256.             (f (cdr pats)
  257.                (cdr temps)
  258.                (parse '() (car pats) (car temps) '() ids))))))))
  259.  
  260.     (define gen-quotes
  261.       (lambda (keys exp ids loops)
  262.     (cond
  263.      ((syntax-match? '(quote *) exp)
  264.       (make-quasi (gen keys (cadr exp) ids loops 0)))
  265.      ((syntax-match? '(quasiquote *) exp)
  266.       (make-quasi (gen keys (cadr exp) ids loops 1)))
  267.      ((pair? exp)
  268.       (let f ((exp exp))
  269.         (if (pair? exp)
  270.         (cons (gen-quotes keys (car exp) ids loops)
  271.               (f (cdr exp)))
  272.         (gen-quotes keys exp ids loops))))
  273.      (else exp))))
  274.  
  275.     (define lookup
  276.       (lambda (exp ids)
  277.     (let loop ((ls ids))
  278.       (cond
  279.        ((null? ls) #f)
  280.        ((equal? (id-name (car ls)) exp) (car ls))
  281.        ((subexp? (id-name (car ls)) exp) #f)
  282.        (else (loop (cdr ls)))))))
  283.  
  284.     (define subexp?
  285.       (lambda (exp1 exp2)
  286.     (and (symbol? exp1)
  287.          (let f ((exp2 exp2))
  288.            (or (eq? exp1 exp2)
  289.            (and (pair? exp2)
  290.             (or (f (car exp2))
  291.                 (f (cdr exp2)))))))))
  292.  
  293.     (define add-control!
  294.       (lambda (id loops)
  295.     (unless (null? id)
  296.         (when (null? loops)
  297.               (kerror "EXTEND-SYNTAX: missing ellipsis in expansion"))
  298.         (let ((x (loop-ids (car loops))))
  299.           (unless (memq id x)
  300.               (loop-ids! (car loops) (cons id x))))
  301.         (add-control! (id-control id) (cdr loops)))))
  302.  
  303.     (define make-loop
  304.       (lambda (loop body)
  305.     (let ((ids (loop-ids loop)))
  306.       (when (null? ids)
  307.         (kerror "EXTEND-SYNTAX: extra ellipsis in expansion"))
  308.       (cond
  309.        ((equal? body (list 'unquote (id-name (car ids))))
  310.         (id-access (car ids)))
  311.        ((and (null? (cdr ids))
  312.          (syntax-match? '(unquote (* *)) body)
  313.          (eq? (cadadr body) (id-name (car ids))))
  314.         `(map ,(caadr body) ,(id-access (car ids))))
  315.        (else
  316.         `(map (lambda ,(map id-name ids) ,(make-quasi body))
  317.           ,@(map id-access ids)))))))
  318.  
  319.     (define match-pattern
  320.       (lambda (keys pat)
  321.     (cond
  322.      ((symbol? pat)
  323.       (if (memq pat keys)
  324.           (if (memq pat '(* \\ ...))
  325.           `(\\ ,pat)
  326.           pat)
  327.           '*))
  328.      ((pair? pat)
  329.       (if (and (pair? (cdr pat))
  330.            (eq? (cadr pat) '...)
  331.            (null? (cddr pat)))
  332.           `(,(match-pattern keys (car pat)) ...)
  333.           (cons (match-pattern keys (car pat))
  334.             (match-pattern keys (cdr pat)))))
  335.      (else pat))))
  336.          
  337.     (define make-quasi
  338.       (lambda (exp)
  339.     (if (and (pair? exp) (eq? (car exp) 'unquote))
  340.         (cadr exp)
  341.         (list 'quasiquote exp))))
  342.  
  343.  
  344.  
  345.  
  346.     (define make-clause
  347.       (lambda (keys cl x)
  348.     (cond
  349.      ((syntax-match? '(* * *) cl)
  350.       (let ((pat (car cl)) (fender (cadr cl)) (exp (caddr cl)))
  351.         (checkpat keys pat pat)
  352.         (let ((ids (parse keys pat x '() '())))
  353.           `((and (syntax-match? ',(match-pattern keys pat) ,x)
  354.              ,(gen-quotes keys fender ids '()))
  355.         ,(make-quasi (gen keys exp ids '() 0))))))
  356.      ((syntax-match? '(* *) cl)
  357.       (let ((pat (car cl)) (exp (cadr cl)))
  358.         (checkpat keys pat pat)
  359.         (let ((ids (parse keys pat x '() '())))
  360.           `((syntax-match? ',(match-pattern keys pat) ,x)
  361.         ,(make-quasi (gen keys exp ids '() 0))))))
  362.      (else
  363.       (kerror "EXTEND-SYNTAX: invalid clause ~o" cl)))))
  364.  
  365.     (define make-syntax
  366.       (let ((x (string->uninterned-symbol "x")))
  367.     (lambda (keys clauses)
  368.       (when (memq '... keys)
  369.         (kerror "EXTEND-SYNTAX: invalid keyword ... in keyword list ~o"
  370.             keys))
  371.       `(lambda (,x)
  372.          (cond
  373.           ,@(map (lambda (cl) (make-clause keys cl x)) clauses)
  374.           (else
  375.            (kerror "~o: invalid syntax ~o" ',(car keys) ,x)))
  376.          ))))
  377.  
  378.  
  379.  
  380.     `(define-macro-both (,(car keys) . body)
  381.  
  382.        (,(make-syntax keys clauses)  (cons ',(car keys) body)))))
  383.  
  384.  
  385.  
  386. (define syntax-match?
  387.    (lambda (pat exp)
  388.       (or (eq? pat '*)
  389.           (eq? exp pat)
  390.           (and (pair? pat)
  391.                (cond
  392.                   ((and (eq? (car pat) '\\)
  393.                         (pair? (cdr pat))
  394.                         (null? (cddr pat)))
  395.                    (eq? exp (cadr pat)))
  396.                   ((and (pair? (cdr pat))
  397.                         (eq? (cadr pat) '...)
  398.                         (null? (cddr pat)))
  399.                    (let ((pat (car pat)))
  400.                       (let f ((lst exp))
  401.                          (or (null? lst)
  402.                              (and (pair? lst)
  403.                                   (syntax-match? pat (car lst))
  404.                                   (f (cdr lst)))))))
  405.                   (else
  406.                    (and (pair? exp)
  407.                         (syntax-match? (car pat) (car exp))
  408.                         (syntax-match? (cdr pat) (cdr exp)))))))))
  409.  
  410.  
  411. (local-assignment syntaxer/default-environment
  412.           'syntax-match?
  413.           syntax-match?)